﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MapLibrary.Utility;
using Animation;
using MapLibrary.Players;
using Enemies;

namespace MapLibrary.Particles
{
    /// <summary>
    /// This class simply manages particles.  It contains a table which associates a name
    /// with a particle pool.  These names are based off of the SpriteTypes that the particles
    /// are created from.  You can get particles through these pools, or you may provide
    /// initial conditions.  When you provide the conditions, the ParticleManager will return
    /// a single particle, or a set of particle that match those conditions.
    /// </summary>
    public class ParticleManager
    {
        private Dictionary<string, Pool<Particle>> particleTable;
        private GameWorld world;

        public ParticleManager(GameWorld world)
        {
            particleTable = new Dictionary<string, Pool<Particle>>();
            this.world = world;

            //read particle types from a file
            //construct pools for each
            //for now, hard coded.
            SpriteType type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/TuberculosisChunk1");
            particleTable.Add("TuberculosisChunk1", new ParticlePool<Particle>(world, type.Clone(), "TuberculosisChunk1"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/TuberculosisChunk2");
            particleTable.Add("TuberculosisChunk2", new ParticlePool<Particle>(world, type.Clone(), "TuberculosisChunk2"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/TuberculosisChunk3");
            particleTable.Add("TuberculosisChunk3", new ParticlePool<Particle>(world, type.Clone(), "TuberculosisChunk3"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/Protein");
            particleTable.Add("Protein", new ParticlePool<ProteinParticle>(world, type.Clone(), "Protein"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/TuberculosisChunk4");
            particleTable.Add("TuberculosisChunk4", new ParticlePool<Particle>(world, type.Clone(), "TuberculosisChunk4"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/TuberculosisChunk5");
            particleTable.Add("TuberculosisChunk5", new ParticlePool<Particle>(world, type.Clone(), "TuberculosisChunk5"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/TuberculosisChunk6");
            particleTable.Add("TuberculosisChunk6", new ParticlePool<Particle>(world, type.Clone(), "TuberculosisChunk6"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/TuberculosisChunk7");
            particleTable.Add("TuberculosisChunk7", new ParticlePool<Particle>(world, type.Clone(), "TuberculosisChunk7"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Bullet");
            particleTable.Add("Bullet", new ParticlePool<Particle>(world, type.Clone(), "Bullet"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/EParticle1");
            particleTable.Add("EParticle1", new ParticlePool<Particle>(world, type.Clone(), "EParticle1"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/EParticle2");
            particleTable.Add("EParticle2", new ParticlePool<Particle>(world, type.Clone(), "EParticle2"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/EParticle3");
            particleTable.Add("EParticle3", new ParticlePool<Particle>(world, type.Clone(), "EParticle3"));
            type = world.ContentManager.Load<SpriteType>(@"Animation/SpriteTypes/Particles/EParticle4");
            particleTable.Add("EParticle4", new ParticlePool<Particle>(world, type.Clone(), "EParticle4"));
        }

        public GameWorld World
        {
            get { return world; }
        }

        public Dictionary<string, Pool<Particle>> Pools
        {
            get { return particleTable; }
        }

        /// <summary>
        /// Retuns a list of particles that match the provided list of initial conditions.  Note
        /// that these particles will already be added into the level through the Sprite.Register
        /// method.
        /// </summary>
        /// <param name="conditions"></param>
        /// <returns></returns>
        public List<Particle> GetFromInitialConditions(List<ParticleInitialConditions> conditions)
        {
            List<Particle> toReturn = new List<Particle>();

            foreach (ParticleInitialConditions cond in conditions)
            {
                toReturn.Add(GetFromInitialConditions(cond));
            }

            return toReturn;
        }

        /// <summary>
        /// Returns a particle that match the provided initial conditions.  Note that this
        /// particle will already be added into the level through the Sprite.Register method.
        /// </summary>
        /// <param name="conditions"></param>
        /// <returns></returns>
        public Particle GetFromInitialConditions(ParticleInitialConditions conditions)
        {
            Particle temp = Pools[conditions.Type].New();

            temp.Body.Position = conditions.Position;
            temp.Body.LinearVelocity = conditions.Velocity;
            temp.Body.IgnoreGravity = !conditions.AffectedByGravity;

            if (conditions.Kinematic)
                temp.Body.BodyType = FarseerPhysics.Dynamics.BodyType.Kinematic;
            else
                temp.Body.BodyType = FarseerPhysics.Dynamics.BodyType.Dynamic;

            temp.Init(conditions.Lifetime);

            World.CurrentLevel.AddSprite(temp);

            return temp;
        }
    }
}
